<!doctype html>



  


<html class="theme-next pisces use-motion" lang="zh-Hans">
<head>
  <meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>



<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />















  
  
  <link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css" />




  
  
  
  

  
    
    
  

  

  

  

  

  
    
    
    <link href="//fonts.googleapis.com/css?family=Lato:300,300italic,400,400italic,700,700italic&subset=latin,latin-ext" rel="stylesheet" type="text/css">
  






<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css" />

<link href="/css/main.css?v=5.1.0" rel="stylesheet" type="text/css" />


  <meta name="keywords" content="C++,编程接口," />








  <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico?v=5.1.0" />






<meta name="description" content="初始化每个Winsock程序必须使用WSAStartup载入合适的Winsock动态链接库，如果载入失败，WSAStartup将返回SOCKET_ERROR，这个错误就是WSANOTINITIALISED。 
当你使用完Winsock接口后，要调用下面的函数对其占用的资源进行释放。">
<meta property="og:type" content="article">
<meta property="og:title" content="Winsock（2/2）">
<meta property="og:url" content="http://yoursite.com/2017/02/26/201702/Winsock2/index.html">
<meta property="og:site_name" content="HoneyGuide's Blog">
<meta property="og:description" content="初始化每个Winsock程序必须使用WSAStartup载入合适的Winsock动态链接库，如果载入失败，WSAStartup将返回SOCKET_ERROR，这个错误就是WSANOTINITIALISED。 
当你使用完Winsock接口后，要调用下面的函数对其占用的资源进行释放。">
<meta property="og:image" content="http://yoursite.com/img/201702/TCPSocket.png">
<meta property="og:updated_time" content="2017-02-27T00:41:08.787Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Winsock（2/2）">
<meta name="twitter:description" content="初始化每个Winsock程序必须使用WSAStartup载入合适的Winsock动态链接库，如果载入失败，WSAStartup将返回SOCKET_ERROR，这个错误就是WSANOTINITIALISED。 
当你使用完Winsock接口后，要调用下面的函数对其占用的资源进行释放。">
<meta name="twitter:image" content="http://yoursite.com/img/201702/TCPSocket.png">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Pisces',
    sidebar: {"position":"left","display":"post","offset":12,"offset_float":0,"b2t":false,"scrollpercent":false},
    fancybox: true,
    motion: true,
    duoshuo: {
      userId: '0',
      author: '博主'
    },
    algolia: {
      applicationID: 'R1W2VDDO1V',
      apiKey: '773854c4c250e5a5cf9cddd97ebcc167',
      indexName: 'Hexo_search',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="http://yoursite.com/2017/02/26/201702/Winsock2/"/>





  <title> Winsock（2/2） | HoneyGuide's Blog </title>
</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">

  














  
  
    
  

  <div class="container one-collumn sidebar-position-left page-post-detail ">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner">﻿<div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/"  class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">HoneyGuide's Blog</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle">Stay hungry & Stay young</p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br />
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-categories">
          <a href="/categories" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-th"></i> <br />
            
            分类
          </a>
        </li>
      
        
        <li class="menu-item menu-item-about">
          <a href="/about" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-user"></i> <br />
            
            关于
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/archives" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br />
            
            归档
          </a>
        </li>
      

      
        <li class="menu-item menu-item-search">
          
            <a href="javascript:;" class="popup-trigger">

　　　　　　<!--增加的代码 start-->

          
            
              <i class="menu-item-icon fa fa-search fa-fw"></i> <br />
            
            搜索
          </a>
        </li>
      
    </ul>
  

  
    <div class="site-search">
      
  <div class="popup local-search-popup">
  <div class="local-search-header clearfix">
    <span class="search-icon">
      <i class="fa fa-search"></i>
    </span>
    <span class="popup-btn-close">
      <i class="fa fa-times-circle"></i>
    </span>
    <div class="local-search-input-wrapper">
      <input autocapitalize="off" autocomplete="off" autocorrect="off" placeholder="搜索..." spellcheck="false" type="text" id="local-search-input">
    </div>
  </div>
  <div id="local-search-result"></div>
</div>



    </div>
  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
    <link itemprop="mainEntityOfPage" href="http://yoursite.com/2017/02/26/201702/Winsock2/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="HoneyGuide">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/avatar.png">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="HoneyGuide's Blog">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
            
            
              
                Winsock（2/2）
              
            
          </h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2017-02-26T00:00:00+08:00">
                2017-02-26
              </time>
            

            

            
          </span>

          
            <span class="post-category" >
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/网络通信/" itemprop="url" rel="index">
                    <span itemprop="name">网络通信</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    


    <div class="post-body" itemprop="articleBody">

      
      

      
        <h3 id="初始化"><a href="#初始化" class="headerlink" title="初始化"></a>初始化</h3><p>每个Winsock程序必须使用WSAStartup载入合适的Winsock动态链接库，如果载入失败，WSAStartup将返回SOCKET_ERROR，这个错误就是WSANOTINITIALISED。 </p>
<p>当你使用完Winsock接口后，要调用下面的函数对其占用的资源进行释放。<br><a id="more"></a></p>
<figure class="highlight plain"><figcaption><span>WSACleanup(void);```</span></figcaption><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"></div><div class="line">如果调用该函数失败也没有什么问题，因为操作系统为自动将其释放，对应于每一个WSAStartup调用都应该有一个WSACleanup调用。</div><div class="line"></div><div class="line">Winsock函数调用失败大多会返回 SOCKET_ERROR(实际上就是-1),你可以调用WSAGetLastError得到错误的详细信息码：</div><div class="line"></div><div class="line">``` int WSAGetLastError (void);</div></pre></td></tr></table></figure>
<h3 id="创建"><a href="#创建" class="headerlink" title="创建"></a>创建</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">SOCKET socket (int af,int type,int protocol);</div></pre></td></tr></table></figure>
<p>af为协议地址族,这里我们使用IPv4,必须为AF_INET</p>
<p>type为socket类型,如果使用TCP/IP,type设为SOCK_STREAM,如果使用UDP,则为SOCK_DGRAM</p>
<p>protocol在给定的地址族及socket类型有多个入口的情况下用来限定特定的传输,对于TCP其值为IPPROTO_TCP,而UDP则为IPPROTO_UDP</p>
<h3 id="绑定"><a href="#绑定" class="headerlink" title="绑定"></a>绑定</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">int bind(int sockfd, struct sockaddr *my_addr,int addrlen);</div></pre></td></tr></table></figure>
<p>bind()函数用在套接字连接建立之前，它的作用是绑定面向连接（connection oriented）的或者面向无连接（transaction oriented）的套接字。当一个套接字被socket函数创建以后，它存在于指定的地址家族里，但是它是匿名的。bind()函数通过安排一个本地名称到未命名的socket建立此socket的本地关联。本地名称包含3个部分：<strong>主机地址、协议号（TCP或UDP）和端口号</strong>。</p>
<p>通常服务器绑定本地地址时，不写死具体的IP（因为IP是软件配置的），而是使用INADDR_ANY，绑定到本地任意地址。何谓“任意地址”呢？考虑多网卡多IP的情况，我们希望服务器应用程序在指定端口监听客户连接，而不管客户数据是通过哪个网卡进来的。这是因为TCP层面往往使用端口是区分不同的应用程序（进程）。</p>
<p>绑定往往具有独占性，某个套接字已经绑定到本机IP地址及端口上时，另一个bind()调用试图再次绑定另一个套接字到该sockaddr的行为将以WSAEADDRINUSE错误告终。</p>
<h3 id="监听"><a href="#监听" class="headerlink" title="监听"></a>监听</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">int listen(  </div><div class="line">    SOCKET s,// [in] Descriptor identifying a bound, unconnected socket.  </div><div class="line">    int backlog// [in] Maximum length of the queue of pending connections.  </div><div class="line">);</div></pre></td></tr></table></figure>
<p>服务器为了接受连接，首先使用socket()函数创建一个套接字，然后使用bind()函数将它绑定到一个本地地址（端口），再用listen()函数为到达的连接指定一个backlog（正在等待连接的最大队列长度）。</p>
<p><strong>服务器在监听之前往往必须调用bind()函数</strong>。即使是在无连接的UDP通信中，准备接收方也需要调用bind()函数。</p>
<p>listen()仅应用在支持连接的套接字上，如SOCK_STREAM类型。函数成功执行之后，套接字s进入了被动模式（passive），到来的连接会被通知，排队等候接受处理。这里着重要提醒的是，传入listen()的套接字是专门用于接受连接的监听套接字，注意区分会话套接字。</p>
<h3 id="连接"><a href="#连接" class="headerlink" title="连接"></a>连接</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">int connect(int sockfd, const struct sockaddr *serv_addr, int addrlen);</div></pre></td></tr></table></figure>
<p>客户端是连接的发起者（initiate），它通过调用connect()函数主动（active）连接服务器。参数二填写欲连接的目标服务器的地址。如果连接的计算机并没有在指定端口上监听，则connect()调用返回SOCKET_ERROR，WSAGetLastError()=WSAECONNREFUSED；另一种错误是WSAETIMEOUT，例如由于路由或网络故障，客户端迟迟接受不到服务器回馈的[SYN,ACK]信号。</p>
<p>客户端往往只是想连接到一个远程主机进行通讯，而并不在乎使用本机上的哪个端口进行通讯（比如Telnet），那么你可以不调用bind()函数，而直接调用connect()函数。系统将会将自动寻找出本地机器上的一个未使用的端口，然后调用bind()来将socket绑定到那个端口上。</p>
<p>在实际应用中，可能需要维持<strong>持久连接</strong>，以提供/接受持续的数据服务，例如HTTP的“Connection: Keep-Alive”。可以调用setsockopt()在SOL_SOCKET级别设置SO_KEEPALIVE选项，这样，套接字将定时向通信对方发送保持活跃数据包，保持心跳。</p>
<p>connect()对于UDP套接字的意义只影响send()调用和接收队列，对recvfrom()和sendto()没有影响,  并且可以多次成功connect()。</p>
<h3 id="接收"><a href="#接收" class="headerlink" title="接收"></a>接收</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">SOCKET accept(  </div><div class="line">    SOCKET s,// [in] Descriptor identifying a socket that has been placed in a listening state with the listen function.  </div><div class="line">    struct sockaddr FAR *addr,// [out] receives the address of the connecting entity, as known to the communications layer.  </div><div class="line">    int FAR *addrlen// [out] the length of addr.  </div><div class="line">);</div></pre></td></tr></table></figure>
<p>服务器进入listen状态后，循环调用accept()接受客户的连接。参数一为监听套接字；参数二为远端客户的地址信息；该函数返回一个套接字句柄，负责后续与该远端客户的会话通信。监听套接字总是默默无闻的在门口守望（listen），迎接（accept）客户端的到来并安会话套接字接收。</p>
<h3 id="IO通信"><a href="#IO通信" class="headerlink" title="IO通信"></a>IO通信</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">int send(  </div><div class="line">       SOCKET s,// [in] Descriptor identifying a connected socket.  </div><div class="line">       const char FAR *buf,// [in] Buffer containing the data to be transmitted.  </div><div class="line">       int len,// [in] Length of the data in buf.  </div><div class="line">       int flags// [in] Indicator specifying the way in which the call is made.  </div><div class="line">);</div></pre></td></tr></table></figure>
<p>send()函数在一个已连接的套接字s上执行数据发送操作。对于客户机而言，发送的目标地址即connect()调用时所指定的地址；对于服务器而言，发送的目标地址即accept()调用所返回的地址。发送的内容为保存在缓冲区buf中，发送的内容长度为len。最后一个参数flags，通常情况下填0。 </p>
<p>只要系统缓冲区足够大，send()执行完拷贝立即返回实际拷贝的字节数。如果系统缓冲区不够大，用户大量地投递send()操作导致TCP Send Socket Buffer迅速充满，此时再调用send()操作，可能返回的值（即实际拷贝字节数）要小于我们传入的期待发送数量（len），在超时不得受理的情况下，返回SOCKET_ERROR，WSAGetLastError()=WSAETIMEDOUT。故大块的数据可能不能一次性“发送”完毕，通常需要检测send()返回值，多次调用send()直到“发送”完毕，可参考CSocket::Send()实现。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">int sendto(  </div><div class="line">        SOCKET s,  </div><div class="line">        const char FAR *buf,  </div><div class="line">        int len,  </div><div class="line">        int flags,  </div><div class="line">        const struct sockaddr FAR *to,// [in] Optional pointer to the address of the target socket.  </div><div class="line">        int tolen// [in] Size of the address in to.  </div><div class="line">);</div></pre></td></tr></table></figure></p>
<p>sendto()函数只是比send()函数多出了一个目的地址信息参数，主要用于面向无连接的UDP通信。TCP套接字在建立连接(connect-accept)时，便知晓对方地址信息，而UDP套接字通信之前不建立连接，需要通信时，调用sendto()将消息发送给指定目的地址(to)。无论对方是否在指定端口“监听”，sendto总是试图把数据发出去，要知道UDP是没有回应确认的。</p>
<p>由于UDP协议基本上只是在IP协议上做了简单的封装（Source Port+Destination Port+Length+Checksum），其没有做可靠性传输保障，故对UDP套接字一次sendto()的数据量不宜过大，一般一次发送512字节左右比较合适。</p>
<p>我们在一个UDP套接字上执行connect()操作，并未真正建立连接，而是执行一种目的地址“绑定”，事后我们可以使用send()函数替换sendto()函数。要取消UDP套接字与目的地址的关联，唯一的办法是在这个套接字上以INADDR_ANY为目标地址调用connect()。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">int recv(  </div><div class="line">       SOCKET s,// [in] Descriptor identifying a connected socket.  </div><div class="line">       char FAR *buf,// [out] Buffer for the incoming data.  </div><div class="line">       int len,// [in] Length of buf.  </div><div class="line">       int flags// [in] Flag specifying the way in which the call is made.  </div><div class="line">);</div></pre></td></tr></table></figure></p>
<p>recv()函数返回实际接收到的数据，可能小于缓冲区的长度len，可能当前到达的有效数据大于len，但最大返回len。在超时仍无数据到来的情况下，返回SOCKET_ERROR，WSAGetLastError()=WSAETIMEDOUT。关于接收超时限制(receive timeout)，可以调用setsockopt()在SOL_SOCKET级别设置SO_RCVTIMEO选项值，以毫秒为单位。建议最多两分钟，因为TCP的MSL（Maximum Segment Lifetime）即为两分钟。</p>
<p>如果对方不停发送数据，而本机过于繁忙疲于应付，则可能导致数据大量累积，一旦TCP Receive Socket Buffer或TCP Window充满，则可能产生数据溢出。TCP滑动窗口机制，由接收方建议性的控制发送量，即每一次确认回应（ACK）时都告知对方自己当前的接收能力（TCP窗口的大小），发送方据此有效地控制自己的发送行为，协调双方的通信步伐。可参考CSocket::Receive()实现。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">int recvfrom(  </div><div class="line">           SOCKET s,  </div><div class="line">           char FAR* buf,  </div><div class="line">           int len,  </div><div class="line">           int flags,  </div><div class="line">           struct sockaddr FAR *from,// [out] Optional pointer to a buffer that will hold the source address upon return.  </div><div class="line">           int FAR *fromlen// [in, out] Optional pointer to the size of the from buffer.  </div><div class="line">);</div></pre></td></tr></table></figure></p>
<p>recvfrom/recv与sendto/send在行为学上同功，因为事先不知发送方为谁，故只要进来的通信，都将对方的地址保存在参数from中。值得注意的是，尽管UDP中没有TCP监听、连接等概念，但是作为接收方往往需要在本地某个端口上等待，这个端口必须是专用，约定对方预知的。故通常在调用recvfrom之前，必须显式调用bind()函数将UDP套接字关联到本地某个指定端口，进行“监听”。</p>
<h3 id="关闭"><a href="#关闭" class="headerlink" title="关闭"></a>关闭</h3><p>在无连接的UDP中不存在关闭连接问题，我们recvfrom/sendto完毕即可调用closesocket()回收套接字内核资源。</p>
<p>对于面向连接的TCP通信，关闭一个连接需要四次挥手，以关闭双向信道。</p>
<p>因为可能该套接字上仍有未决的I/O，为了保证通信方能够接收到应用程序发出的所有数据，一个友好的应用程序应该通知接收端“不再发送数据”，同样通信对方也应该如此，这就是所谓的“从容关闭”。TCP套接字recv()/send()通信完毕，往往需要调用shutdown()函数从容地关闭TCP连接，而不是立刻调用closesocket()函数释放套接字资源。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">int shutdown(  </div><div class="line">           SOCKET s,// [in] Descriptor identifying a socket.  </div><div class="line">           int how// [in] Flag that describes what types of operation will no longer be allowed.  </div><div class="line">);</div></pre></td></tr></table></figure></p>
<p>在没有调用shutdown()的情况下，直接调用<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">int closesocket(SOCKET s);</div></pre></td></tr></table></figure></p>
<p>试图释放TCP套接字资源，如果没有对该套接字的其他引用（具体来说是该套接字上是否存在未决I/O），那么所有与该套接字描述符关联的资源都会被释放，其中包括所有传输队列中的数据，包括同步调用和重叠操作。在TCP层面上，closesocket()将向对方发送[RST,ACK]报文，以重置虚拟链路。</p>
<p><img src="/img/201702/TCPSocket.png" alt="image"></p>
<hr>
<h3 id="广播"><a href="#广播" class="headerlink" title="广播"></a>广播</h3><p>广播包通常为了如下两个原因使用：</p>
<ol>
<li>一个应用程序希望在本地网络中找到一个资源，而应用程序对于该资源的地址又没有任何先验的知识。 </li>
<li>一些重要的功能，例如路由要求把它们的信息发送给所有找到的邻机。</li>
</ol>
<p>被广播信息的目的地址取决于这一信息将在何种网络上广播。Internet域中支持一个速记地址用于广播－INADDR_BROADCAST。由于使<br>用广播以前必须捆绑一个数据报套接口，所以所有收到的广播消息都带有发送者的地址和端口。</p>
<p>广播通信是无连接的通信，通信前不需要建立连接。不需要listen和accept，但需要绑定一个socket用来接收广播。</p>
<h3 id="CAsyncSocket对象"><a href="#CAsyncSocket对象" class="headerlink" title="CAsyncSocket对象"></a>CAsyncSocket对象</h3><p>异步套接字对象</p>
<p>使用CAsyncSocket进行网络编程，可以充分利用Windows操作系统提供的消息驱动机制，通过应用程序框架来传递消息，方便地处理各种网络事件。另一方面，作为MFC微软基础类库中的一员，CAsyncSocket可以和MFC的其他类融为一体，大大扩展了网络编程的空间，方便了编程。</p>
<h3 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h3><p><a href="http://blog.csdn.net/phunxm/article/details/5085825" target="_blank" rel="external">http://blog.csdn.net/phunxm/article/details/5085825</a><br><a href="http://www.cnblogs.com/howareyou586/archive/2009/02/28/1400262.html" target="_blank" rel="external">http://www.cnblogs.com/howareyou586/archive/2009/02/28/1400262.html</a><br><a href="http://blog.csdn.net/opkl8877/article/details/52232355" target="_blank" rel="external">http://blog.csdn.net/opkl8877/article/details/52232355</a><br><a href="http://network.51cto.com/art/201412/459619_all.htm" target="_blank" rel="external">http://network.51cto.com/art/201412/459619_all.htm</a></p>

      
    </div>

    <div>
      
        

      
    </div>

    <div>
      
        

      
    </div>


    <footer class="post-footer">
      
        <div class="post-tags">
          
            <a href="/tags/C/" rel="tag"># C++</a>
          
            <a href="/tags/编程接口/" rel="tag"># 编程接口</a>
          
        </div>
      

      
        
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/2017/02/26/201702/同步异步阻塞非阻塞/" rel="prev" title="同步异步阻塞非阻塞">
                同步异步阻塞非阻塞 <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </article>



    <div class="post-spread">
      
    </div>
  </div>

          
          </div>
          


          
  <div class="comments" id="comments">
    
  </div>


        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap" >
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview">
            站点概览
          </li>
        </ul>
      

      <section class="site-overview sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
          <img class="site-author-image" itemprop="image"
               src="/images/avatar.png"
               alt="HoneyGuide" />
          <p class="site-author-name" itemprop="name">HoneyGuide</p>
           
              <p class="site-description motion-element" itemprop="description"></p>
          
        </div>
        <nav class="site-state motion-element">
        
          
            <div class="site-state-item site-state-posts">
              <a href="/archives">
                <span class="site-state-item-count">29</span>
                <span class="site-state-item-name">日志</span>
              </a>
            </div>
          

          
            <div class="site-state-item site-state-categories">
              <a href="/categories">
                <span class="site-state-item-count">5</span>
                <span class="site-state-item-name">分类</span>
              </a>
            </div>
          

          
            <div class="site-state-item site-state-tags">
              
                <span class="site-state-item-count">34</span>
                <span class="site-state-item-name">标签</span>
              
            </div>
          

        </nav>

        

        <div class="links-of-author motion-element">
          
        </div>

        
        

        
        

        


      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-3"><a class="nav-link" href="#初始化"><span class="nav-number">1.</span> <span class="nav-text">初始化</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#创建"><span class="nav-number">2.</span> <span class="nav-text">创建</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#绑定"><span class="nav-number">3.</span> <span class="nav-text">绑定</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#监听"><span class="nav-number">4.</span> <span class="nav-text">监听</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#连接"><span class="nav-number">5.</span> <span class="nav-text">连接</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#接收"><span class="nav-number">6.</span> <span class="nav-text">接收</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#IO通信"><span class="nav-number">7.</span> <span class="nav-text">IO通信</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#关闭"><span class="nav-number">8.</span> <span class="nav-text">关闭</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#广播"><span class="nav-number">9.</span> <span class="nav-text">广播</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#CAsyncSocket对象"><span class="nav-number">10.</span> <span class="nav-text">CAsyncSocket对象</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#参考"><span class="nav-number">11.</span> <span class="nav-text">参考</span></a></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright" >
  
  &copy; 
  <span itemprop="copyrightYear">2017</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">HoneyGuide</span>
</div>


<div class="powered-by">
  由 <a class="theme-link" href="https://hexo.io">Hexo</a> 强力驱动
</div>

<div class="theme-info">
  主题 -
  <a class="theme-link" href="https://github.com/iissnan/hexo-theme-next">
    NexT.Pisces
  </a>
</div>


        

        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    
    
  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  




  
  <script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>

  
  <script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>

  
  <script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>

  
  <script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>

  
  <script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>

  
  <script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.1.0"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.1.0"></script>



  
  


  <script type="text/javascript" src="/js/src/affix.js?v=5.1.0"></script>

  <script type="text/javascript" src="/js/src/schemes/pisces.js?v=5.1.0"></script>



  
  <script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.0"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.1.0"></script>



  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.0"></script>



  



  




	





  





  





  



  
  
  <script type="text/javascript">
    // Popup Window;
    var isfetched = false;
    // Search DB path;
    var search_path = "search.xml";
    if (search_path.length == 0) {
      search_path = "search.xml";
    }
    var path = "/" + search_path;
    // monitor main search box;

    function proceedsearch() {
      $("body").append('<div class="local-search-pop-overlay">').css('overflow', 'hidden');
      $('.popup').toggle();
    }
    // search function;
    var searchFunc = function(path, search_id, content_id) {
      'use strict';
      $.ajax({
        url: path,
        dataType: "xml",
        async: true,
        success: function( xmlResponse ) {
          // get the contents from search data
          isfetched = true;
          $('.popup').detach().appendTo('.header-inner');
          var datas = $( "entry", xmlResponse ).map(function() {
            return {
              title: $( "title", this ).text(),
              content: $("content",this).text(),
              url: $( "url" , this).text()
            };
          }).get();
          var $input = document.getElementById(search_id);
          var $resultContent = document.getElementById(content_id);
          $input.addEventListener('input', function(){
            var matchcounts = 0;
            var str='<ul class=\"search-result-list\">';
            var keywords = this.value.trim().toLowerCase().split(/[\s\-]+/);
            $resultContent.innerHTML = "";
            if (this.value.trim().length > 1) {
              // perform local searching
              datas.forEach(function(data) {
                var isMatch = false;
                var content_index = [];
                var data_title = data.title.trim().toLowerCase();
                var data_content = data.content.trim().replace(/<[^>]+>/g,"").toLowerCase();
                var data_url = decodeURIComponent(data.url);
                var index_title = -1;
                var index_content = -1;
                var first_occur = -1;
                // only match artiles with not empty titles and contents
                if(data_title != '') {
                  keywords.forEach(function(keyword, i) {
                    index_title = data_title.indexOf(keyword);
                    index_content = data_content.indexOf(keyword);
                    if( index_title >= 0 || index_content >= 0 ){
                      isMatch = true;
                      if (i == 0) {
                        first_occur = index_content;
                      }
                    }

                  });
                }
                // show search results
                if (isMatch) {
                  matchcounts += 1;
                  str += "<li><a href='"+ data_url +"' class='search-result-title'>"+ data_title +"</a>";
                  var content = data.content.trim().replace(/<[^>]+>/g,"");
                  if (first_occur >= 0) {
                    // cut out 100 characters
                    var start = first_occur - 20;
                    var end = first_occur + 80;
                    if(start < 0){
                      start = 0;
                    }
                    if(start == 0){
                      end = 50;
                    }
                    if(end > content.length){
                      end = content.length;
                    }
                    var match_content = content.substring(start, end);
                    // highlight all keywords
                    keywords.forEach(function(keyword){
                      var regS = new RegExp(keyword, "gi");
                      match_content = match_content.replace(regS, "<b class=\"search-keyword\">"+keyword+"</b>");
                    });

                    str += "<p class=\"search-result\">" + match_content +"...</p>"
                  }
                  str += "</li>";
                }
              })};
            str += "</ul>";
            if (matchcounts == 0) { str = '<div id="no-result"><i class="fa fa-frown-o fa-5x" /></div>' }
            if (keywords == "") { str = '<div id="no-result"><i class="fa fa-search fa-5x" /></div>' }
            $resultContent.innerHTML = str;
          });
          proceedsearch();
        }
      });}

    // handle and trigger popup window;
    $('.popup-trigger').click(function(e) {
      e.stopPropagation();
      if (isfetched == false) {
        searchFunc(path, 'local-search-input', 'local-search-result');
      } else {
        proceedsearch();
      };
    });

    $('.popup-btn-close').click(function(e){
      $('.popup').hide();
      $(".local-search-pop-overlay").remove();
      $('body').css('overflow', '');
    });
    $('.popup').click(function(e){
      e.stopPropagation();
    });
  </script>


  

  

  

  


  

</body>
</html>
